package com.panshi.controller.reg;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.panshi.api.UserApi;
import com.panshi.po.UserPO;
import com.panshi.sendEmail.SendEmailIdentifyServiceImp;
import com.panshi.vo.ResponseVO;
import com.panshi.vo.UserAddVO;
import com.panshi.vo.UserBean;
import com.panshi.vo.UserLogicVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Controller
@Slf4j
@RequestMapping("/reg")
public class RegController {

    @Autowired
    private UserApi userApi;

    @Autowired
    private RedisTemplate<String,String> template;

    @Resource
    private SendEmailIdentifyServiceImp sendEmailIdentifyService;

    /**
     * 注册用户
     * @param userAddVO
     * @return
     * @throws JsonProcessingException
     */
    @PostMapping("/register")
    @ResponseBody
    public Map<Object,Object> register(UserAddVO userAddVO) throws JsonProcessingException {

        Map<Object,Object> map = new HashMap<>();

        String id = userAddVO.getEmail();
        String value = "1";
        Long maxTime = 5L;

        Boolean bool = template.execute(new RedisCallback<Boolean>(){
            @Override
            public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {

                Boolean boo = redisConnection.setNX(id.getBytes(),value.getBytes());
                if(!boo){
                    log.info("该邮箱正在注册");
                    return true;
                }
                //设置过期时间，防止JVM服务关闭导致不释放锁
                redisConnection.expire(id.getBytes(),maxTime);

                //时间任务对象
                Timer timer = new Timer();
                try{
                    //延长锁的过期时间
                    taskSchedule(timer,id,value,maxTime);

                    ResponseVO<UserPO> vo = userApi.findUserByEmail(userAddVO.getEmail());

                    if(null == vo.getData() || "".equals(vo.getData())){
                        //获取访问者的IP地址
                        String ip = InetAddress.getLocalHost().getHostAddress();
                        userApi.userAdd(userAddVO);
                        map.put("success",true);
                        map.put("message","注册成功");
                    }else{
                        map.put("success",false);
                        map.put("message","该邮箱号码已经注册了");
                    }
                    //模拟5s，用户注册
                    Thread.sleep(5*1000);

                } catch (InterruptedException | UnknownHostException e) {
                    e.printStackTrace();
                }finally {
                    //取消这个延长锁任务
                    timer.cancel();

                    //处理结束后
                    log.info("注册结束");
                    redisConnection.del(id.getBytes());
                }

                return Boolean.FALSE;
            }
        });

        return map;
    }

    /**
     * 这个用个定时任务把这个锁时间延长
     * @param timer
     * @param key
     * @param val
     * @param timeOut
     */
    private void taskSchedule(Timer timer,String key,String val,Long timeOut){
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.info("执行延迟时间了========>{}",timeOut);
                template.opsForValue().set(key, val, timeOut, TimeUnit.SECONDS);
            }
        }, 0, 2000);
    }

    /**
     * 校验邮箱验证码是否正确
     * @param userBean
     * @return
     */
    @PostMapping("/sendIdentify")
    @ResponseBody
    public Map<String,Object> checkSend(UserBean userBean){
        Map<String,Object> map = new HashMap<>();
        String ident = template.opsForValue().get("验证码："+userBean.getEmail());
        log.info("邮箱验证码==========>"+ident);
        //判断是否发送过邮箱验证码
        if(null == ident){
            map.put("success",false);
            map.put("message","验证码已过期");
            return map;
        }
        System.out.println("identify:"+userBean.getIdentify());
        System.out.println("ident:"+ident);
        if(!ident.equals(userBean.getIdentify())){
            map.put("success",false);
            map.put("message","验证码错误");
            return map;
        }
        map.put("success",true);
        map.put("message","验证码正确");
        return map;
    }

}
